package com.kh.rationaldrugreview.service;

import com.kh.rationaldrugreview.entity.EntityAlias;
import com.kh.rationaldrugreview.entity.EntityRelationship;
import com.kh.rationaldrugreview.entity.KnowledgeEntity;
import com.kh.rationaldrugreview.mapper.KnowledgeEntityMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 知识实体服务
 * 负责实体的去重、标准化和管理
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class KnowledgeEntityService {
    
    private final KnowledgeEntityMapper knowledgeEntityMapper;
    
    // 缓存已处理的实体，减少数据库查询
    private final Map<String, KnowledgeEntity> entityCache = new ConcurrentHashMap<>();
    
    /**
     * 查找或创建实体
     * 这是核心的去重方法，确保同一概念只有一个实体
     * 
     * @param entityType 实体类型
     * @param entityName 实体名称
     * @param attributes 实体属性
     * @param source 来源
     * @return 规范化的实体（已存在或新创建）
     */
    @Transactional
    public KnowledgeEntity findOrCreateEntity(String entityType, String entityName, 
                                             Map<String, Object> attributes, String source) {
        // 1. 标准化名称
        String canonicalName = normalizeEntityName(entityType, entityName);
        
        // 2. 检查缓存
        String cacheKey = entityType + ":" + canonicalName;
        if (entityCache.containsKey(cacheKey)) {
            KnowledgeEntity cached = entityCache.get(cacheKey);
            // 增加频次
            knowledgeEntityMapper.incrementFrequency(cached.getEntityId());
            return cached;
        }
        
        // 3. 从数据库查找
        KnowledgeEntity existingEntity = knowledgeEntityMapper.findByTypeAndCanonicalName(entityType, canonicalName);
        
        if (existingEntity != null) {
            // 实体已存在，更新频次和属性
            knowledgeEntityMapper.incrementFrequency(existingEntity.getEntityId());
            
            // 合并新的属性
            if (attributes != null && !attributes.isEmpty()) {
                Map<String, Object> mergedAttributes = mergeAttributes(existingEntity.getAttributes(), attributes);
                existingEntity.setAttributes(mergedAttributes);
                knowledgeEntityMapper.update(existingEntity);
            }
            
            // 添加到缓存
            entityCache.put(cacheKey, existingEntity);
            
            log.debug("Found existing entity: type={}, name={}, id={}", 
                entityType, entityName, existingEntity.getEntityId());
            
            return existingEntity;
        }
        
        // 4. 检查是否为已知实体的别名
        KnowledgeEntity entityByAlias = knowledgeEntityMapper.findByAlias(entityName);
        if (entityByAlias != null && entityByAlias.getEntityType().equals(entityType)) {
            // 是已知实体的别名
            knowledgeEntityMapper.incrementFrequency(entityByAlias.getEntityId());
            entityCache.put(cacheKey, entityByAlias);
            
            log.debug("Found entity by alias: type={}, alias={}, id={}", 
                entityType, entityName, entityByAlias.getEntityId());
            
            return entityByAlias;
        }
        
        // 5. 创建新实体
        KnowledgeEntity newEntity = new KnowledgeEntity();
        newEntity.setEntityType(entityType);
        newEntity.setEntityName(entityName);
        newEntity.setCanonicalName(canonicalName);
        newEntity.setDisplayName(entityName);
        newEntity.setAttributes(attributes);
        newEntity.setSource(source);
        newEntity.setFrequency(1);
        newEntity.setConfidenceScore(BigDecimal.ONE);
        newEntity.setIsValidated(false);
        newEntity.setIsActive(true);
        newEntity.setCreatedBy("system");
        newEntity.setUpdatedBy("system");
        
        // 处理别名
        List<String> aliases = extractAliases(entityName, attributes);
        if (!aliases.isEmpty()) {
            newEntity.setAliases(aliases);
        }
        
        knowledgeEntityMapper.insert(newEntity);
        
        // 添加到缓存
        entityCache.put(cacheKey, newEntity);
        
        log.info("Created new entity: type={}, name={}, id={}", 
            entityType, entityName, newEntity.getEntityId());
        
        // 6. 保存别名
        if (aliases != null && !aliases.isEmpty()) {
            for (String alias : aliases) {
                saveAlias(newEntity.getEntityId(), alias, "synonym", source);
            }
        }
        
        return newEntity;
    }
    
    /**
     * 标准化实体名称
     * 根据实体类型应用不同的标准化规则
     */
    private String normalizeEntityName(String entityType, String name) {
        if (name == null) return "";
        
        // 基础标准化：去除首尾空格，统一空格
        String normalized = name.trim().replaceAll("\\s+", " ");
        
        // 根据实体类型进行特定的标准化
        switch (entityType) {
            case "DRUG":
                // 药品名称标准化
                normalized = normalizeDrugName(normalized);
                break;
            case "DISEASE":
            case "SYMPTOM":
                // 疾病/症状名称标准化
                normalized = normalizeMedicalTerm(normalized);
                break;
            case "PATIENT_PROFILE":
                // 患者特征标准化
                normalized = normalizePatientProfile(normalized);
                break;
            default:
                // 默认转换为小写
                normalized = normalized.toLowerCase();
                break;
        }
        
        return normalized;
    }
    
    /**
     * 药品名称标准化
     */
    private String normalizeDrugName(String name) {
        // 移除常见的剂型后缀
        String normalized = name
            .replaceAll("(片|胶囊|颗粒|注射液|口服液|滴丸|软膏|乳膏|栓剂|贴剂)$", "")
            .replaceAll("(tablets?|capsules?|injection|solution|cream|ointment)$", "");
        
        // 统一括号格式
        normalized = normalized
            .replaceAll("（", "(")
            .replaceAll("）", ")");
        
        // 去除多余的空格
        return normalized.trim();
    }
    
    /**
     * 医学术语标准化
     */
    private String normalizeMedicalTerm(String term) {
        // 统一中文标点
        String normalized = term
            .replaceAll("、", ",")
            .replaceAll("；", ";")
            .replaceAll("：", ":");
        
        // 移除"症"、"病"等后缀的重复
        normalized = normalized
            .replaceAll("症症", "症")
            .replaceAll("病病", "病");
        
        return normalized.trim();
    }
    
    /**
     * 患者特征标准化
     */
    private String normalizePatientProfile(String profile) {
        // 统一年龄段表示
        String normalized = profile
            .replaceAll("老年人?", "老年")
            .replaceAll("儿童期?", "儿童")
            .replaceAll("成年人?", "成人");
        
        // 统一性别表示
        normalized = normalized
            .replaceAll("男性", "男")
            .replaceAll("女性", "女");
        
        return normalized.trim();
    }
    
    /**
     * 合并实体属性
     * 保留原有属性，添加新属性，更新已有属性
     */
    private Map<String, Object> mergeAttributes(Map<String, Object> existing, Map<String, Object> newAttrs) {
        if (existing == null) {
            return newAttrs != null ? new HashMap<>(newAttrs) : new HashMap<>();
        }
        
        Map<String, Object> merged = new HashMap<>(existing);
        
        if (newAttrs != null) {
            for (Map.Entry<String, Object> entry : newAttrs.entrySet()) {
                String key = entry.getKey();
                Object newValue = entry.getValue();
                
                if (!merged.containsKey(key)) {
                    // 新属性，直接添加
                    merged.put(key, newValue);
                } else {
                    // 已存在的属性，根据类型决定如何合并
                    Object existingValue = merged.get(key);
                    merged.put(key, mergeAttributeValue(existingValue, newValue));
                }
            }
        }
        
        return merged;
    }
    
    /**
     * 合并单个属性值
     */
    private Object mergeAttributeValue(Object existing, Object newValue) {
        if (existing == null) return newValue;
        if (newValue == null) return existing;
        
        // 如果都是列表，合并并去重
        if (existing instanceof List && newValue instanceof List) {
            Set<Object> merged = new LinkedHashSet<>((List<?>) existing);
            merged.addAll((List<?>) newValue);
            return new ArrayList<>(merged);
        }
        
        // 如果都是Map，递归合并
        if (existing instanceof Map && newValue instanceof Map) {
            Map<String, Object> merged = new HashMap<>((Map<String, Object>) existing);
            merged.putAll((Map<String, Object>) newValue);
            return merged;
        }
        
        // 其他情况，新值覆盖旧值
        return newValue;
    }
    
    /**
     * 从属性中提取可能的别名
     */
    private List<String> extractAliases(String entityName, Map<String, Object> attributes) {
        List<String> aliases = new ArrayList<>();
        
        if (attributes != null) {
            // 检查是否有明确的别名字段
            if (attributes.containsKey("aliases")) {
                Object aliasObj = attributes.get("aliases");
                if (aliasObj instanceof List) {
                    for (Object alias : (List<?>) aliasObj) {
                        if (alias != null) {
                            aliases.add(alias.toString());
                        }
                    }
                }
            }
            
            // 检查其他可能包含别名的字段
            if (attributes.containsKey("synonyms")) {
                Object synonymObj = attributes.get("synonyms");
                if (synonymObj instanceof List) {
                    for (Object synonym : (List<?>) synonymObj) {
                        if (synonym != null) {
                            aliases.add(synonym.toString());
                        }
                    }
                }
            }
            
            // 对于药品，通用名和商品名可能不同
            if (attributes.containsKey("genericName") && !entityName.equals(attributes.get("genericName"))) {
                aliases.add(attributes.get("genericName").toString());
            }
            if (attributes.containsKey("brandName") && !entityName.equals(attributes.get("brandName"))) {
                aliases.add(attributes.get("brandName").toString());
            }
        }
        
        // 去重
        return new ArrayList<>(new LinkedHashSet<>(aliases));
    }
    
    /**
     * 保存实体别名
     */
    @Transactional
    public void saveAlias(Long entityId, String aliasName, String aliasType, String source) {
        // 检查别名是否已存在
        List<EntityAlias> existingAliases = knowledgeEntityMapper.findAliasesByEntityId(entityId);
        for (EntityAlias existing : existingAliases) {
            if (existing.getAliasName().equals(aliasName)) {
                // 别名已存在
                return;
            }
        }
        
        // 创建新别名
        EntityAlias alias = new EntityAlias();
        alias.setEntityId(entityId);
        alias.setAliasName(aliasName);
        alias.setAliasType(aliasType);
        alias.setLanguage("zh_CN");
        alias.setSource(source);
        alias.setConfidenceScore(BigDecimal.ONE);
        alias.setIsActive(true);
        
        knowledgeEntityMapper.insertAlias(alias);
        
        log.debug("Saved alias: entityId={}, alias={}", entityId, aliasName);
    }
    
    /**
     * 查找或创建关系
     */
    @Transactional
    public EntityRelationship findOrCreateRelationship(Long sourceEntityId, Long targetEntityId,
                                                      String relationshipType, Map<String, Object> properties,
                                                      Integer strength, String source) {
        // 查找已存在的关系
        EntityRelationship existing = knowledgeEntityMapper.findRelationship(
            sourceEntityId, targetEntityId, relationshipType);
        
        if (existing != null) {
            // 关系已存在，可能需要更新属性
            if (properties != null && !properties.isEmpty()) {
                Map<String, Object> mergedProps = mergeAttributes(existing.getProperties(), properties);
                existing.setProperties(mergedProps);
                if (strength != null) {
                    existing.setStrength(strength);
                }
                knowledgeEntityMapper.updateRelationship(existing);
            }
            return existing;
        }
        
        // 创建新关系
        EntityRelationship relationship = new EntityRelationship();
        relationship.setSourceEntityId(sourceEntityId);
        relationship.setTargetEntityId(targetEntityId);
        relationship.setRelationshipType(relationshipType);
        relationship.setProperties(properties);
        relationship.setStrength(strength);
        relationship.setConfidenceScore(BigDecimal.ONE);
        relationship.setSource(source);
        relationship.setIsValidated(false);
        relationship.setIsActive(true);
        
        knowledgeEntityMapper.insertRelationship(relationship);
        
        log.debug("Created relationship: {} -> {} [{}]", 
            sourceEntityId, targetEntityId, relationshipType);
        
        return relationship;
    }
    
    /**
     * 更新实体的Neo4j节点ID
     */
    @Transactional
    public void updateNeo4jNodeId(Long entityId, String neo4jNodeId) {
        KnowledgeEntity entity = knowledgeEntityMapper.findById(entityId);
        if (entity != null) {
            entity.setNeo4jNodeId(neo4jNodeId);
            knowledgeEntityMapper.update(entity);
            
            // 更新缓存
            String cacheKey = entity.getEntityType() + ":" + entity.getCanonicalName();
            entityCache.put(cacheKey, entity);
        }
    }
    
    /**
     * 更新关系的Neo4j ID
     */
    @Transactional
    public void updateNeo4jRelationshipId(Long relationshipId, String neo4jRelationshipId) {
        EntityRelationship relationship = new EntityRelationship();
        relationship.setRelationshipId(relationshipId);
        relationship.setNeo4jRelationshipId(neo4jRelationshipId);
        knowledgeEntityMapper.updateRelationship(relationship);
    }
    
    /**
     * 根据实体类型和名称查找实体
     */
    public KnowledgeEntity findEntity(String entityType, String name) {
        // 先标准化名称
        String canonicalName = normalizeEntityName(entityType, name);
        
        // 检查缓存
        String cacheKey = entityType + ":" + canonicalName;
        if (entityCache.containsKey(cacheKey)) {
            return entityCache.get(cacheKey);
        }
        
        // 从数据库查找
        return knowledgeEntityMapper.findByTypeAndName(entityType, name);
    }
    
    /**
     * 清空缓存
     */
    public void clearCache() {
        entityCache.clear();
        log.info("Entity cache cleared");
    }
    
    /**
     * 获取统计信息
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalEntities", knowledgeEntityMapper.countEntities());
        stats.put("totalRelationships", knowledgeEntityMapper.countRelationships());
        stats.put("cacheSize", entityCache.size());
        return stats;
    }
}